package com.pingbu.tijian.hospital.backapi.service;


import com.pingbu.common.utils.PbSecretUtils;
import com.pingbu.tijian.hospital.backapi.bean.entity.*;
import com.pingbu.tijian.hospital.backapi.mapper.KspwClassroomMapper;
import com.pingbu.tijian.hospital.backapi.mapper.KspwStudentMapper;
import com.pingbu.tijian.hospital.backapi.mapper.KspwStudentSeatMapper;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.*;

/**
 * 用于考试排座位的类
 * 临时功能
 * 本类将学生信息从excel中导入到mysql中
 */
@Service
public class KspwStudentService {

    private static Logger logger = LoggerFactory.getLogger(KspwStudentService.class);

    @Autowired
    private KspwStudentMapper kspwStudentMapper;
    @Autowired
    private KspwStudentSeatMapper kspwStudentSeatMapper;
    @Autowired
    private KspwClassroomMapper kspwClassroomMapper;


    /**
     * 导入学生的Excel
     */
    public void importStudentExcel(){

        // 获取所有教室的座位号
        KspwClassroom kcr = new KspwClassroom();
        List<KspwClassroom> classrooms = this.kspwClassroomMapper.list(kcr);

        // 1 读取Excel文件
        String strExcelDir = "D:\\works\\顽石科技\\1020月考\\各班座位";

        File fi1 = new File(strExcelDir);

        for(File fi2 : fi1.listFiles()) {

            File fExcelPath = fi2;
            Workbook wb1 = null;
            try {
                wb1 = WorkbookFactory.create(fExcelPath);

                Sheet sheet1 = wb1.getSheetAt(0);

                int lastRowNum = sheet1.getLastRowNum();

                for (int i = 1; i <= lastRowNum; i++) {
                    Row row1 = sheet1.getRow(i);

                    Cell cell1 = row1.getCell(0);
                    Cell cell2 = row1.getCell(1);
                    Cell cell3 = row1.getCell(2);
                    Cell cell4 = row1.getCell(3);
                    Cell cell5 = row1.getCell(4);

                    String strName = getCellValue(cell1);
                    String strBanji = getCellValue(cell2);
                    String strStatic = getCellValue(cell3);

                    String strRoomName = getCellValue(cell4);

                    String strSeatNum = getCellValue(cell5);

                    if (!("是").equals(strStatic)) {
                        strRoomName = null;
                        strSeatNum = null;
                    }

                    Integer iSeatNumb = null;
                    if (strSeatNum != null) {
                        iSeatNumb = Integer.valueOf(strSeatNum);
                    }

                    // 判断学号是否超过了班级座位数
                    if(strRoomName!=null && iSeatNumb!=null) {
                        int scnt = this.getSeatCountFromClassrooms(classrooms, strRoomName);
                        if (iSeatNumb != null && scnt < iSeatNumb) {
                            System.out.println("学号过大：：教室" + strRoomName + " 座位数："
                                    + scnt + ", 学生：" + strName + " 学号：" + iSeatNumb + "");
                        }
                    }
                    saveStudent(strName, strBanji, strRoomName, iSeatNumb);

                }


            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (wb1 != null) {
                    try {
                        wb1.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

    /**
     * 根据班级座位数，刷新座位编号 t_kspw_student_seat
     */
    public void refreshRoomSeat(){

        // 1 读出所有的班级
        List<KspwClassroom> lst1Room = kspwClassroomMapper.list(new KspwClassroom());

        // 2 清空 KspwStudentSeat
        kspwStudentSeatMapper.delete();

        // 3 遍历每个班级，并填充学生作为表
        for(KspwClassroom kcroom: lst1Room){

            for(int i =1;i<=kcroom.getSeat_count();i++){

                KspwStudentSeat ksseat = new KspwStudentSeat();
                ksseat.setNoid(PbSecretUtils.uuid());
                ksseat.setRoom_name(kcroom.getRoom_name());
                ksseat.setSeat_numb(i);

                kspwStudentSeatMapper.insert(ksseat);
            }

        }
    }

    /**
     * 导出班级座位号，用于打印
     */
    public void exportBanjiSeat(){

        // 1 获取所有班级
        KspwStudentSeat stu3 = new KspwStudentSeat();
        List<KspwStudentSeat> kbj1Lst = kspwStudentSeatMapper.list2(stu3);

        String strExcelPath = "d:/banji_seat.xlsx";
        FileOutputStream fos1 = null;
        File fExcelPath = new File(strExcelPath);
        Workbook wb1 = null;
        try {
            wb1 = WorkbookFactory.create(true);

            // 增加sheet
            Sheet sheet1 = wb1.createSheet("学生排位");
            int rowNum = 0;
            for(KspwStudentSeat kcr2: kbj1Lst){

                Row row1 = sheet1.createRow(rowNum++);

                Cell cell1 = row1.createCell(0);
                cell1.setCellValue(kcr2.getBanji_name());

                Cell cell2 = row1.createCell(1);
                cell2.setCellValue(kcr2.getStudent_name());

                Cell cell3 = row1.createCell(2);
                cell3.setCellValue(kcr2.getRoom_name());

                Cell cell4 = row1.createCell(3);
                cell4.setCellValue(kcr2.getSeat_numb());

            }

            fos1 = new FileOutputStream(strExcelPath);
            wb1.write(fos1);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(fos1!=null){
                try {
                    fos1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if(wb1!=null){
                try {
                    wb1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 刷新数据表 t_kspw_student_seat
     */
    public void refreshStudentSeat(){

        // 1 清除学生座位
        kspwStudentSeatMapper.clearStudentSeat();

        // 2 获取各班级信息
        List<KspwBanji> banjis = listBanaji();
        refreshNotStaticStudent(banjis);

        // 获取所有固定座位的学生
        KspwStudent staticStudent = new KspwStudent();
        staticStudent.setStatic(true);
        List<KspwStudent> lstStaticStudent = kspwStudentMapper.list(staticStudent);

        Map<String,KspwStudent> mapStaticStudent = new HashMap<>();
        lstStaticStudent.forEach((stu4)->{
            mapStaticStudent.put(stu4.getStatic_room_name()+"-"+stu4.getStatic_seat_numb(), stu4 );
        });

        // 4 获取所有座位
        KspwStudentSeat sseat10 = new KspwStudentSeat();
        List<KspwStudentSeat> sseatList = kspwStudentSeatMapper.list(sseat10);


        Random rnd1=new Random();
        // 5 遍历每个座位
        List<KspwStudentSeat> preSeats = new LinkedList<>();
        for(KspwStudentSeat sseat2: sseatList){

            // 获取前一个座位的学生所在班级，作为忽略班级
            List<String> ignoreBanjis = new ArrayList<>();
            preSeats.forEach((seat5)->{ ignoreBanjis.add(seat5.getBanji_name()); });

            String seatKey = sseat2.getRoom_name()+"-"+sseat2.getSeat_numb();
            KspwStudent staticStudent3 = mapStaticStudent.get(seatKey);

            KspwStudent stu3 = null;
            if(staticStudent3!=null){
                stu3 = staticStudent3;
            }else{
                // 1.1 获取学生的数量
                Integer stuAllCount = getStudentCountFromBanjis(banjis);
                if(stuAllCount==0){
                    break;
                }
                int stuIndex = rnd1.nextInt(stuAllCount);
                stu3 = pollStudentFromBanjis(banjis, stuIndex, ignoreBanjis);
            }

            if(stu3 !=null){

                sseat2.setStudent_id(stu3.getNoid());
                sseat2.setStudent_name(stu3.getStudent_name());
                sseat2.setBanji_name(stu3.getBanji_name());

                kspwStudentSeatMapper.update(sseat2);

                // 把前一个座位放到集合中
                if(preSeats!=null&&preSeats.size()>2){
                    preSeats.remove(0);
                }
                preSeats.add(sseat2);
            }
        }

    }


    /**
     * 保存学生信息到数据表 t_kspw_student
     * @param studentName
     * @param banjiName
     */
    public void saveStudent(String studentName, String banjiName,
                            String staticRoomName,Integer staticSeatNumb){

        KspwStudent stu1 = new KspwStudent();
        stu1.setStudent_name(studentName);
        stu1.setBanji_name(banjiName);

        KspwStudent stu1Res = kspwStudentMapper.get(stu1);

        if(stu1Res==null){
            stu1.setNoid(PbSecretUtils.uuid());
            stu1.setStatic_room_name(staticRoomName);
            stu1.setStatic_seat_numb(staticSeatNumb);

            kspwStudentMapper.insert(stu1);
        }else{

            stu1Res.setStatic_room_name(staticRoomName);
            stu1Res.setStatic_seat_numb(staticSeatNumb);

            kspwStudentMapper.update(stu1Res);
        }
        

    }

    /**
     * 列出班级，并且舒心班级的学生列表
     * @return
     */
    private List<KspwBanji> listBanaji(){
        List<KspwBanji> banjis = kspwStudentMapper.listBanji();
        return banjis;
    }

    private void refreshNotStaticStudent(List<KspwBanji> lstBanji){
        // 3 刷新各班级学生列表
        for(KspwBanji bj1 : lstBanji){

            String bjName = bj1.getBanji_name();

            KspwStudent st1 = new KspwStudent();
            st1.setBanji_name( bjName );
            st1.setStatic(false);
            List<KspwStudent> st1s = kspwStudentMapper.list(st1);

            bj1.setStudents(st1s);
        }
    }

    private Integer getStudentCountFromBanjis(List<KspwBanji> param){
        int cnt = 0 ;
        for(KspwBanji bj2: param){
            if(bj2.getStudents()!=null){
                cnt+= bj2.getStudents().size();
            }
        }
        return cnt;
    }

    private Integer getSeatCountFromClassrooms(List<KspwClassroom> param, String roomName){

        for(KspwClassroom cr2: param){
            if(cr2.getRoom_name().equals(roomName)){
                return cr2.getSeat_count();
            }
        }
        return 0;
    }

    private KspwStudent pollStudentFromBanjis(List<KspwBanji > banjiList, int index,
                                              List<String> ignoreBanji){

        KspwStudent st3 = null;

        // 判断是否有可忽略的班级
        boolean canIgnoreBanji = false;
        if(ignoreBanji!=null) {
            for (KspwBanji bj3 : banjiList) {
                if (bj3.getStudents() != null && bj3.getStudents().size() > 0
                        && !ignoreBanji.contains(bj3.getBanji_name())) {
                    canIgnoreBanji = true;
                    break;
                }
            }
        }

        while(true) {
            int examCount = 0;
            for (KspwBanji bj3 : banjiList) {
                if (bj3.getStudents() == null|| bj3.getStudents().size()==0) {
                    continue;
                }

                // 如果是忽略的班级，则不处理
                if(canIgnoreBanji && ignoreBanji!=null && ignoreBanji.contains(bj3.getBanji_name())){
                    continue;
                }

                if (bj3.getStudents().size() > index) {
                    st3 = bj3.getStudents().get(index);
                    bj3.getStudents().remove(index);
                    examCount += index;
                    break;
                } else {
                    index -= bj3.getStudents().size();
                    examCount += bj3.getStudents().size();
                }

            }

            // 一个都没检测，或 找到学生了
            if(examCount==0 || index<0 || st3!=null){
                break;
            }
        }

        return st3;
    }

    private String getCellValue(Cell cell4){
        String strVal = null;
        if(cell4!=null){
            if(CellType.STRING == cell4.getCellType()){
                strVal = cell4.getStringCellValue();
            }else if(CellType.NUMERIC == cell4.getCellType()){
                strVal = String.valueOf( Double.valueOf( cell4.getNumericCellValue()).intValue());
            }
        }
        return strVal;

    }

}
